﻿(function(window){

muZoom._MODE = {

	'follow' : {
		methods : {
			init : function(){
				this._stylesFollow = null;
				this._repairFollowLeft = 0;
				this._repairFollowTop = 0;
			},
			load : function(){
				var 
					viewer = this._viewer,
					style = viewer.style,
					styles;
					
				this._stylesFollow = {
					left : style.left,
					top : style.top,
					position : style.position
				};
				
				viewer.style.position = 'absolute';
				
				if(!viewer.offsetWidth){
					styles = {
						display : style.display,
						visibility : style.visibility
					};
					$$OBEA.setStyle(viewer, {
						display : 'block',
						visibility : 'hidden'
					});
				}
				
				this._repairFollowLeft = viewer.offsetWidth / 2;
				this._repairFollowTop = viewer.offsetHeight / 2;
				
				if(!/BODY|HTML/.test(viewer.offsetParent.nodeName)){
					var 
						parent = viewer.offsetParent,
						rect = $$OBEA.rect(parent);
					
					this._repairFollowLeft += rect.left + parent.clientLeft;
					this._repairFollowTop += rect.top + parent.clientTop;
				}
				
				if(styles){
					$$OBEA.setStyle(viewer, styles);
				}
			},
			// repair : function(e, pos){
				// var 
					// zoom = this._zoom,
					// viewerWidth = this._viewerWidth,
					// viewerHeight = this._viewerHeight;
				
				// pos.left = ( viewerWidth / 2 - pos.left ) * ( viewerWidth / zoom.width - 1 );
				// pos.top = ( viewerHeight / 2 - pos.top ) * ( viewerHeight / zoom.height - 1 );
				
			// },
			move : function(e){
				var 
					style = this._viewer.style;
				
				style.left = e.pageX - this._repairFollowLeft + 'px';
				style.top = e.pageY - this._repairFollowTop + 'px';
			},
			destroy : function(){
				$$OBEA.setStyle(this._viewer, this._stylesFollow);
			}
		}
	},
	
	'handle' : {
		options : {
			handle : ''
		},
		methods : {
			init : function(){
				var handle = document
					.getElementById(this.options.handle);
				if(!handle){
					var body = document.body;
					handle = body.insertBefore(this._viewer.cloneNode(false), 
						body.childNodes[0]);
					handle.id = '';
					handle['_createbyhandle'] = true;
				}else{
					var style = handle.style;
					this._stylesHandle = {
						left : style.left,
						top : style.top,
						position : style.position,
						display : style.display,
						visibility : style.visibility,
						padding : style.padding,
						margin : style.margin,
						width : style.width,
						height : style.height
					};
				}
				$$OBEA.setStyle(handle, {
					padding : 0,
					margin : 0,
					display : 'none'
				});
				this._handle = handle;
				this._repairHandleLeft = 0;
				this._repairHandleTop = 0;
			},
			
			load : function(){
				var 
					handle = this._handle,
					rect = this._rect;
				
				$$OBEA.setStyle(handle, {
					position : 'absolute',
					width : this._rangeWidth + 'px',
					height : this._rangeHeight + 'px',
					display : 'block',
					visibility : 'hidden'
				});
				
				this._repairHandleLeft = rect.left + 
					this._repairLeft - handle.clientLeft;
				this._repairHandleTop = rect.top + 
					this._repairTop - handle.clientTop;
				
				if(!/BODY|HTML/.test(handle.offsetParent.nodeName)){
					var 
						parent = handle.offsetParent,
						rect = $$OBEA.rect(parent);
					
					this._repairHandleLeft -= rect.left + 
									parent.clientLeft;
					this._repairHandleTop -= rect.top +
									parent.clientTop;
				}
				$$OBEA.setStyle(handle, {
					display : 'none',
					visibility : 'visible'
				});
			},
			
			start : function(){
				this._handle.style.display = 'block';
			},
			
			move : function(e, x, y){
				var 
					style = this._handle.style,
					scale = this._scale;
				
				style.left = Math.ceil(this._repairHandleLeft - 
						x / scale) + 'px';
				style.top = Math.ceil(this._repairHandleTop - 
						y / scale) + 'px';
			},
			
			end : function(){
				this._handle.style.display = 'none';
			},
			
			destroy : function(){
				if('_createbyhandle' in this._handle){
					document.body.removeChild(this._handle);
				}else{
					$$OBEA.setStyle(this._handle, this._stylesHandle);
				}
				this._handle = null;
			}
		}
	},
	
	'cropper' : {
		options : {
			opacity : .5
		},
		methods : {
			init : function(){
				var 
					body = document.body,
					cropper = body.insertBefore(document.
					createElement('img'), body.childNodes[0]);
				
				cropper.style.display = 'none';
				
				this._cropper = cropper;
				this.opacity = this.options.opacity;
			},
			load : function(){
				var 
					cropper = this._cropper,
					image = this._image,
					rect = this._rect;
				
				cropper.src = image.src;
				cropper.width = image.width;
				cropper.height = image.height;
				$$OBEA.setStyle(cropper, {
					position : 'absolute',
					left : rect.left + this._repairLeft + 'px',
					top : rect.top + this._repairTop + 'px'
				});
			},
			start : function(){
				this._cropper.style.display = 'block';
				$$OBEA.setStyle(this._image, 'opacity', this.opacity);
			},
			move : function(e, x, y){
				var 
					w = this._rangeWidth,
					h = this._rangeHeight,
					scale = this._scale;
					
				x = Math.ceil(-x / scale);
				y = Math.ceil(-y / scale);
				
				this._cropper.style.clip = 'rect(' + y +
					'px ' + (x + w) + 'px ' + (y + h) +
					'px ' + x + 'px)';
			},
			end : function(){
				$$OBEA.setStyle(this._image, 'opacity', 1);
				this._cropper.style.display = 'none';
			},
			destroy : function(){
				$$OBEA.setStyle(this._image, 'opacity', 1);
				document.body.removeChild(this._cropper);
				this._cropper = null;			
			}
		}
	}
};

muZoom.prototype._init = function(){
	var 
		init = muZoom.prototype._init,
		mode = muZoom._MODE,
		modes = {
			'follow' : [mode.follow],
			'handle' : [mode.handle],
			'cropper' : [mode.cropper]
		};
		
	return function(){
		var options = arguments[0][2];
		if(options && options.mode && modes[options.mode]){
			$$OBEA.forEach(modes[options.mode], function(mode){
				
				$$OBEA.extend(options, mode.options, false);
				
				$$OBEA.forEach(mode.methods, function(method, name){
					$$OBEA.selfe.addEvent(this, name, method);
				}, this);
			}, this);
		}
		init.apply(this, Array.prototype.slice.apply(arguments));
	}
}();
})(window)